// Author: Kanno
// Capture video first frame
// https://caniuse.com/?search=requestVideoFrameCallback
// https://wicg.github.io/video-rvfc/#video-frame-metadata-callback-attributes

import './rvfc-polyfill'

export async function captureVideoFrame (url, options = {}) {
  const { quality = 0.5 } = options
  const canvas = document.createElement('canvas')
  const video = document.createElement('video')
  if (window.CanvasCaptureMediaStreamTrack && window.MediaStreamTrackProcessor) {
    try {
      const { track } = await getVideoTrack(url, video)
      const processor = new MediaStreamTrackProcessor(track)
      const reader = processor.readable.getReader()
      const bitmap = await readChunk(reader)
      canvas.height = bitmap.height
      canvas.width = bitmap.width
      canvas.getContext('2d').drawImage(bitmap, 0, 0)
      const URI = canvas.toDataURL('image/jpeg', quality)
      return Promise.resolve(URI)
    } finally {
      canvas.remove()
      video.remove()
    }
  } else {
    video.crossOrigin = 'anonymous'
    video.src = url
    video.muted = true
    document.body.append(video)
    await video.play()
    return new Promise((resolve, reject) => {
      try {
        video.requestVideoFrameCallback((now, metadata) => {
          canvas.height = metadata.height
          canvas.width = metadata.width
          canvas.getContext('2d').drawImage(video, 0, 0, canvas.width, canvas.height)
          const URI = canvas.toDataURL('image/jpeg', quality)
          canvas.remove()
          video.remove()
          resolve(URI)
        })
      } catch (error) {
        console.log(error)
        canvas.remove()
        video.remove()
        reject('rvfc polyfill error.Check it.')
      }
    })
  }
}

async function readChunk (reader) {
  const { done, value } = await reader.read()
  if (value) {
    const bitmap = await createImageBitmap(value)
    value.close()
    return Promise.resolve(bitmap)
  }
}

export function b64ToBlob (url, filename) {
  const arr = url.split(',')
  const mime = arr[0].match(/:(.*?);/)[1]
  const bytes = atob(arr[1])
  let n = bytes.length
  const ia = new Uint8Array(n)
  while (n--) { ia[n] = bytes.charCodeAt(n) }

  return new File([ia], filename, { type: mime })
}

export async function getVideoTrack (url, video) {
  video.crossOrigin = 'anonymous'
  video.src = url
  video.muted = true
  document.body.append(video)
  await video.play()
  const [track] = video.captureStream().getVideoTracks()
  video.onended = evt => track.stop()
  return { track }
}

export async function getVideoDuration (url) {
  const video = document.createElement('video')
  video.crossOrigin = 'anonymous'
  video.src = url
  video.muted = true
  document.body.append(video)

  try {
    await video.play()
    return new Promise((resolve) => {
      video.addEventListener('canplaythrough', function listener () {
        video.removeEventListener('canplaythrough', listener)
        resolve(video.duration * 1000)
      })
    })
  } finally {
    video.remove()
  }
}
export function getCropImg (url, prop = {}, baseURL = '...') {
  const fileName = new URL(url).pathname
  const draft = {
    bucket: 'sports-shop-resource',
    edits: { resize: prop },
    key: fileName.substring(1, fileName.length)
  }
  return baseURL + btoa(JSON.stringify(draft))
}
